package edu.gmu.atelier;

/**
 * Small number used to test equality of values.  Given two double numbers
 * d1 and d2, they are similar if |(d1-d2)| &lt e.
 * <p>  
 * The similar methods are all absolute error measurements - for relative
 * you are on your own.  Also all types are double.
 * @author James H. Pope
 */
public class Epsilon
{
    /*
     *  Machine epsilon 2.220446049250313E-16
     */
    public static final double MACHINE_EPS = 2.220446049250313E-16;
    public static final Epsilon E = new Epsilon(MACHINE_EPS);
    
    private double eps = 0;
    
    private Epsilon( double eps )
    {
        this.eps = eps;
    }
    
    public boolean similar( double d1, double d2 )
    {
        return doubleEquals( d1, d2, this.eps );
    }
    
    public String toString()
    {
        return new Double(this.eps).toString();
    }
    
    
    //------------------------------------------------------------------------//
    // Static Utility methods
    //------------------------------------------------------------------------//
    public static Epsilon makeDecimal( int signDigits )
    {
        return new Epsilon( 1.0 / Math.pow(10, signDigits) );
        //return new EpsilonDouble( DOUBLE_EPS * Math.pow(10, signDigits) );
        //return new EpsilonDouble( DOUBLE_EPS * Math.pow(2, signDigits) );
    }
    
    public static Epsilon makeBinary( int signDigits )
    {
        return new Epsilon( 1.0 / Math.pow(2, signDigits) );
        //return new EpsilonDouble( DOUBLE_EPS * Math.pow(10, signDigits) );
        //return new EpsilonDouble( DOUBLE_EPS * Math.pow(2, signDigits) );
    }
    
    public static boolean doubleEquals( double d1, double d2, double eps )
    {
        //return Math.abs( d1-d2 ) >= DOUBLE_EPS;
        return Math.abs( d1-d2 ) <  eps;
    }
    
}
